package org.internna.expensetracker.mvc;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Locale;

import org.springframework.ui.ModelMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.internna.expensetracker.model.Subcategory;
import org.internna.expensetracker.model.budget.CategoryBudget;
import org.internna.expensetracker.model.budget.MonthlyBudget;
import org.internna.expensetracker.model.security.UserDetails;
import org.internna.expensetracker.model.support.Interval;
import org.internna.expensetracker.model.support.NameValuePair;
import org.internna.expensetracker.services.AccountService;

@Controller
@RequestMapping("/financial/budget/**")
public class BudgetController {

	private static final Log logger = LogFactory.getLog(BudgetController.class);

	@Autowired private AccountService accountService;

    @RequestMapping("manage")
    public String manage(ModelMap modelMap) {
    	UserDetails user = UserDetails.findCurrentUser();
    	modelMap.addAttribute("budgets", user.getBudget().getBudgets());
    	modelMap.addAttribute("categories", Subcategory.findExpenseCategories(user));
        return "budget/manage";
    }

    @RequestMapping(value = "manage", method = RequestMethod.POST)
    public String manage(String currency, long subcategory, int month, double amount, ModelMap modelMap) {
    	UserDetails user = UserDetails.findCurrentUser();
    	Subcategory loaded = Subcategory.findSubcategory(subcategory);
    	if (month == -1) {
    		for (int i = 0; i < 12; i++) {
    			createBudget(user, currency, i, amount, loaded);
    		}
    	} else {
    		createBudget(user, currency, month, amount, loaded);
    	}
    	return manage(modelMap);
    }

    protected void createBudget(UserDetails user, String locale, int month, double amount, Subcategory category) {
    	CategoryBudget categoryBudget = new CategoryBudget();
    	categoryBudget.setCategory(category);
    	String[] locales = locale.split("_");
    	categoryBudget.setLocale(new Locale(locales[0], locales[1], ""));
    	categoryBudget.setExpectedAmount(new BigDecimal(amount));
    	MonthlyBudget monthlyBudget = obtainMonthlyBudget(user, month);
    	categoryBudget.setMonthlyBudget(monthlyBudget);
    	categoryBudget.persist();
    	monthlyBudget.getBudgets().add(categoryBudget);
    	monthlyBudget.merge();
    }

    protected MonthlyBudget obtainMonthlyBudget(UserDetails user, int month) {
    	return user.getBudget().getMonthlyBudget(month);
    }

    @RequestMapping(value = "update", method = RequestMethod.POST)
    public @ResponseBody Boolean update(long id, double value) {
    	CategoryBudget budget = getBudget(id);
    	if (budget != null) {
    		budget.setExpectedAmount(new BigDecimal(value));
    		budget.merge();
    	}
    	return budget != null && budget.getExpectedAmount().doubleValue() == value;
    }

    @RequestMapping(value = "delete", method = RequestMethod.POST)
    public @ResponseBody Boolean delete(Long id) {
    	boolean deleted = false;
    	try {
	    	CategoryBudget budget = getBudget(id);
	    	if (budget != null) {
	    		budget.remove();
	    		deleted = true;
	    	}
    	} catch (Exception ex) {
    		logger.warn("Error deleting category [" + id + "]", ex);
    	}
    	return deleted;
    }

    private CategoryBudget getBudget(long id) {
    	UserDetails user = UserDetails.findCurrentUser();
    	CategoryBudget budget = CategoryBudget.findCategoryBudget(id);
    	return budget != null && user != null && budget.getMonthlyBudget().getBudget().getOwner().equals(user) ? budget : null;
    }

    @RequestMapping("graph/{expanded}")
    public String widget(@PathVariable String expanded, ModelMap modelMap) {
    	BigDecimal budgeted = BigDecimal.ZERO;
    	BigDecimal expended = BigDecimal.ZERO;
    	UserDetails user = UserDetails.findCurrentUser();
    	Interval monthToDate = new Interval(Interval.Intervals.MONTH_TO_DATE);
    	MonthlyBudget budget = user.getBudget().getMonthlyBudget(Calendar.getInstance().get(Calendar.MONTH));
    	for (CategoryBudget categoryBudget : budget.getBudgets()) {
    		budgeted = budgeted.add(categoryBudget.getExpectedAmount());
    		BigDecimal expendedInCategory = accountService.getExpenses(user, categoryBudget.getLocale(), categoryBudget.getCategory(), monthToDate); 
    		expended = expended.add(expendedInCategory);
    		categoryBudget.setExpended(expendedInCategory);
    	}
    	modelMap.addAttribute("expanded", expanded);
		modelMap.addAttribute("categories", budget.getBudgets());
    	modelMap.addAttribute("totals", new NameValuePair<Double, Double>(expended.doubleValue(), budgeted.doubleValue()));
    	return "budget/widget";
    }

}
